/*
 * Classe statica con vari metodi utili
 */

package utility;

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;

/**
 *
 * @author dario
 */
public class Utility 
{
    public static final int RED_CH = 0;
    public static final int GREEN_CH = 1;
    public static final int BLUE_CH = 2;
    
    /*
     * Disegna il pezzo di immagine newPiece nell'immagine image alle coordinate x,y(NORD_WEST)
     */
    public static void substituteSubImage(BufferedImage newPiece, BufferedImage image, int x, int y)
    {
        image.getGraphics().drawImage(newPiece, x, y, null);
    }
    
    public static void writeImageToFile(BufferedImage im, String basedir, String filename, String ext) throws IOException
    {
        File file = new File(basedir+"/"+filename+"."+ext);
        ImageIO.write(im, ext, file);
    }
    
    public static BufferedImage getChannel(int ch, BufferedImage inImg)
    {
        BufferedImage result = new BufferedImage(inImg.getWidth(), inImg.getHeight(), inImg.getType());
        for (int i=0 ; i< inImg.getHeight(); i++)
            for (int j=0 ; j< inImg.getWidth(); j++) 
            {
                int cl = 0;
                switch(ch) {
                    case RED_CH:
                        cl = new Color(inImg.getRGB(j, i)).getRed();
                        break;
                    case BLUE_CH:
                        cl = new Color(inImg.getRGB(j, i)).getBlue();
                        break;
                    default:
                        cl = new Color(inImg.getRGB(j, i)).getGreen();
                        break;
                            
                }
                
                result.setRGB(j, i, new Color(cl, cl, cl).getRGB());
            }
        return result;
    }
    
    
    public static BufferedImage mergeChannel(BufferedImage imgRed, BufferedImage imgGreen, BufferedImage imgBlue)    
    {
        BufferedImage result = new BufferedImage(imgRed.getWidth(), imgRed.getHeight(), imgRed.getType());
        for (int i=0 ; i< imgRed.getHeight(); i++)
            for (int j=0 ; j< imgRed.getWidth(); j++) 
            {
                int red = new Color(imgRed.getRGB(j, i)).getRed();
                int green = new Color(imgGreen.getRGB(j, i)).getGreen();
                int blue = new Color(imgBlue.getRGB(j, i)).getBlue();
                result.setRGB(j, i, new Color(red, green, blue).getRGB());
            }
        
        return result;
                
    }
    
    public static BufferedImage getScaledInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality)
    {
        int type = (img.getTransparency() == Transparency.OPAQUE) ?
            BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage ret = (BufferedImage)img;
        int w, h;
        if (higherQuality) {
            // Use multi-step technique: start with original size, then
            // scale down in multiple passes with drawImage()
            // until the target size is reached
            w = img.getWidth();
            h = img.getHeight();
        } else {
            // Use one-step technique: scale directly from original
            // size to target size with a single drawImage() call
            w = targetWidth;
            h = targetHeight;
        }
        
        do {
            if (higherQuality && w > targetWidth) {
                w /= 2;
                if (w < targetWidth) {
                    w = targetWidth;
                }
            }

            if (higherQuality && h > targetHeight) {
                h /= 2;
                if (h < targetHeight) {
                    h = targetHeight;
                }
            }

            BufferedImage tmp = new BufferedImage(w, h, type);
            Graphics2D g2 = tmp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(ret, 0, 0, w, h, null);
            g2.dispose();

            ret = tmp;
        } while (w != targetWidth || h != targetHeight);

        return ret;
    }
    
    public static int getMedianValue(int[] array)
    {
        //System.out.println("Dimensione array:"+array.length);
        if(array.length==0)
            return 0;
        
        for(int i=0; i<array.length-1; i++)
        {
            for(int j=i; j<array.length; j++)
            {
                if(array[i]>array[j])
                {
                    int aux = array[j];
                    array[j] = array[i];
                    array[i] = aux;
                }
            }
        }
        return array[array.length/2];
    }
    
    public static void medianFilter(BufferedImage image, int window_width)
    {
    	int step = window_width / 2;
    	
    	for (int x = step; x<image.getWidth() - step; x++)
    		for (int y = step; y<image.getHeight() - step; y++)
    		{
    	       int[] redArray = new int[window_width*window_width];
    	       int[] greenArray = new int[window_width*window_width];
    	       int[] blueArray = new int[window_width*window_width];
    	       int counter = 0;
    	       for (int i = 0; i< window_width; i++)
    	    	   for (int j = 0; j< window_width; j++)
    	    	   {
    	    		   Color c = new Color (image.getRGB(x + i - step, y + j - step));
    	    		   redArray[counter] = c.getRed();
    	    		   greenArray[counter] = c.getGreen();
    	    		   blueArray[counter] = c.getBlue();
    	    		   counter++;
    	    	   }
    	       Color result = new Color(getMedianValue(redArray),getMedianValue(greenArray),getMedianValue(blueArray));
    	       image.setRGB(x, y, result.getRGB());
    	    		   
    		}       
    }
}
